/*





*/

#include <stdlib.h>
#include <dos.h>
#include "mpx_supt.h"
#include "commhand.h"
#include "pcbCom.h"
#include "r3code.h"
#include "r4code.h"


//Functions

int load(char* name,int p, enum pcbClass c){
	pcb* newPtr = 0;
	context* cp = 0;
	int progLen = NULL;
	int startOff = NULL;
	
	//check program & get its length and offset
	int err = sys_check_program("\0",name,&progLen,&startOff);
	if(err) return err;
	//printf("Checked data: name=%s, progLen=%d, startOff=%d\n",name,*progLenPtr,*startOffPtr);
	
	//set up pcb
	newPtr = setup_pcb(name,p,c);
	if(!newPtr) return ERR_PCB_EXISTS;
	
	//set pcb to suspended ready
	newPtr->isSuspended = TRUE;
	newPtr->state = READY;
	
	//set program size, load address, and execution address
	//TODO: fix this!
	newPtr->memSize = progLen;
	newPtr->loadAddr = (unsigned char*)sys_alloc_mem(sizeof(unsigned char)*(newPtr->memSize));
	newPtr->execAddr = newPtr->loadAddr + startOff;
	
	//set pcb context
	cp = (context *) newPtr->stackTop;
	cp->IP = FP_OFF(newPtr->execAddr); 
	cp->CS = FP_SEG(newPtr->execAddr); 
	cp->DS = _DS;
	cp->ES = _ES;
	cp->FLAGS = 0x200;
	 
	 //load program
	 err = sys_load_program(newPtr->loadAddr,newPtr->memSize,"\0",name);
	 if(err) return err;
	 
	 //insert into READY queue
	 err = insert_pcb(newPtr,getQ(READY));
	 return err;
}

//Permanent Commands

int load_command(char args[MAX_NARGS][MAX_ARGLEN], int nArgs){
	int err = 0;
	int* priPtr = NULL;
	if(nArgs < 0) return 0;
	if(!strcmp(args[0],"LOAD")){
		if(nArgs == 2){
			err = load(args[1],0,APPLICATION);
			print_r4_err(err);
		}
		else if(nArgs == 3){
			if(getPriority(args[2],priPtr)){
				err = load(args[1],*priPtr,APPLICATION);
				print_r4_err(err);
			}	
		}
		else {
			printf("Error: improper syntax for command LOAD.\n"
					"Acceptable syntax:\n"
					"LOAD <process name> [<priority>]\n");
		}
		return 1;
	}
	return 0;
}

int terminate_pcb_command(char args[MAX_NARGS][MAX_ARGLEN], int nArgs){
	int remerr = 0, delerr = 0;
	pcb *toDeletePtr;
	if(nArgs<1 || strcmp(args[0],"TERMINATE")) return 0;
	if(nArgs == 2){
		toDeletePtr = find_pcb(args[1]);
		if(!toDeletePtr) {
			printf("Error: unable to find process %s.\n",args[1]);
			return 1;
		}
		if(toDeletePtr->class == SYSTEM) {
			printf("Error: permission to terminate SYSTEM process denied.\n");
			return 1;
		}
		remerr = remove_pcb(toDeletePtr);
		delerr = free_pcb(toDeletePtr);
		//if(remerr<0) printf("Error: unable to successfully remove pcb.\n");
		//if(delerr<0) printf("Error: unable to successfully delete pcb.\n");
		if(!(remerr+delerr)) /*debugging only*/;
		printf("Process %s has been successfully deleted.\n",toDeletePtr->name);
	}
	return 1;
}

void print_r4_err(int err){
	switch(err){
		case 0: printf("Program successfully loaded.\n");
				break;
		case ERR_PCB_EXISTS: printf("Error: process/program name redundancy.\n"); 
							break;
		case ERR_SUP_NAMLNG: printf("Error: program pathname is too long.\n"); 
							break;
		case ERR_SUP_FILINV: printf("Error: file is not valid.\n"); 
							break;
		case ERR_SUP_FILNFD: printf("Error: file not found.\n"); 
							break;
		case ERR_SUP_PROGSZ: printf("Error: program too big for region.\n"); 
							break;
		case ERR_SUP_LDADDR: printf("Error: invalid load address.\n"); 
							break;
		case ERR_SUP_LDFAIL: printf("Error: load failed.\n"); 
							break;
		default: printf("An unknown error occurred.\n"); 
				break;
	}
}


